<!--
 * @Author: wfl
 * @LastEditors: fj
 * @description:
 * @updateInfo:
 * @Date: 2022-05-17 14:43:45
 * @LastEditTime: 2024-02-23 14:44:00
-->
<script lang="ts" setup>
import { computed, PropType, toRef } from "vue";
import {
  useDataCenter,
  getFieldMap,
} from "@/components/_mixins/use-data-center";
import { useApiStore } from "@/store/api";
import RankBoard from "./rank-board";

const props = defineProps({
  com: {
    type: Object as PropType<RankBoard>,
    required: true,
    default: () => ({}),
  },
});

useDataCenter(props.com);

const apiStore = useApiStore();
const dv_data = computed(() => {
  return apiStore.dataMap[props.com.id]?.source ?? [];
});

const config = toRef(props.com, "config");

const attr = toRef(props.com, "attr");

const fixData = computed(() => {
  return dv_data.value.map((v, i) => {
    const value = dv_data.value.map(({ value }) => value);
    const min = Math.min(...value) || 0;
    // abs of min
    const minAbs = Math.abs(min);
    const max = Math.max(...value) || 0;
    const total = max + minAbs;
    return {
      ...v,
      name: v[dv_field.value.name],
      value: v[dv_field.value.value],
      ranking: i + 1,
      percent: ((v.value + minAbs) / total) * 100,
    };
  });
});

const dv_field = computed(() => {
  return getFieldMap(props.com.apis.source.fields);
});

const swiper = computed(() => config.value.swiper);

const wrapperStyle = computed(() => {
  return {
    width: `${attr.value.w}px`,
    height: `${attr.value.h}px`,
  };
});

const prefixStyle = computed(() => {
  return config.value.prefixStyle;
});
const textStyle = computed(() => {
  return config.value.textStyle;
});

const numStyle = computed(() => {
  return config.value.numStyle;
});
// 标题样式
const computedInfoName = computed(() => {
  const { fontSize, fontFamily, fontWeight, color, left, lineHeight } =
    textStyle.value;
  return {
    lineHeight: useNumberToPx(lineHeight),
    fontSize: useNumberToPx(fontSize),
    fontFamily,
    fontWeight,
    marginLeft: useNumberToPx(left),
    color: setChartColor(color),
  };
});
// 排名样式
const computedRankName = computed(() => {
  const { fontSize, fontFamily, fontWeight, color } = prefixStyle.value;
  return {
    fontSize: useNumberToPx(fontSize),
    fontFamily,
    fontWeight,
    color: setChartColor(color),
  };
});
// 右侧数值样式
const computedRankValue = computed(() => {
  const { fontSize, fontFamily, fontWeight, color } = numStyle.value;

  return {
    fontSize: useNumberToPx(fontSize),
    fontFamily,
    fontWeight,
    color: setChartColor(color),
  };
});
// 进度条样式
const computedInsideColumn = (item, index) => {
  const { radius, color } = config.value.barStyle;
  const heights = config.value.barStyle.height;
  const { show, rote, width, split } = config.value.split;
  const sp = 100 - split;
  return show
    ? {
        width: `${item.percent}%`,
        height: useNumberToPx(heights),
        borderRadius: useNumberToPx(radius).join(" "),
        backgroundSize: `${width}px ${heights}px`,
        backgroundImage: `linear-gradient(${rote}deg, ${config.value.generate.color[index]} 0%, ${config.value.generate.color[index]} ${sp}%, transparent ${sp}%, transparent 100%)`,
      }
    : {
        width: `${item.percent}%`,
        height: useNumberToPx(heights),
        borderRadius: useNumberToPx(radius).join(" "),
        ...setChartColor(color),
        background: config.value.generate.color[index],
      };
};

const getMargin = computed(() => {
  const { marginLeft } = config.value.numStyle;
  return {
    marginLeft: useNumberToPx(marginLeft),
  };
});

// 主背景背景色
const progressBgStyle = () => {
  const { show, background, rote, width, split } = config.value.split;
  const { height } = config.value.barStyle;
  const sp = 100 - split;
  return show
    ? {
        left: `${width / 2}px`,
        backgroundSize: `${width}px ${height}px`,
        backgroundImage: `linear-gradient(${rote}deg, ${background} 0%, ${background} ${sp}%, transparent ${sp}%, transparent 100%)`,
      }
    : {
        background: background,
      };
};
</script>

<template>
  <div class="datav-wrapper" :style="wrapperStyle">
    <GlSwiper
      :length="fixData.length"
      :loop="swiper.loop"
      :row="swiper.row"
      :col="swiper.col"
      :space-between="swiper.spaceBetween"
      :autoplay="{
        autoplay: swiper.autoplay.autoplay,
        delay: swiper.autoplay.delay,
        pauseOnMouseEnter: true,
      }"
      :direction="swiper.direction"
      :effect="swiper.effect"
      :slides-per-group="swiper.slidesPerGroup"
    >
      <template v-for="(item, index) in fixData" :key="item" #[index+1]>
        <div class="row-item">
          <div class="ranking-info">
            <div class="rank" :style="computedRankName">
              {{ prefixStyle.prefix }}{{ item.ranking }}
            </div>
            <div
              class="info-name"
              :style="computedInfoName"
              v-html="item.name"
            ></div>
            <div class="ranking-value" :style="computedRankValue">
              <span v-if="config.numStyle.configType !== 'percent'">{{
                item.value
              }}</span>
              <span
                v-if="config.numStyle.configType !== 'num'"
                :style="getMargin"
                >{{
                  item.percent !== 100 ? item.percent.toFixed(2) : item.percent
                }}</span
              >
              {{ config.default.unit }}
            </div>
          </div>
          <div class="ranking-column" :style="progressBgStyle()">
            <div
              class="inside-column"
              :style="computedInsideColumn(item, index)"
            >
              <div class="shine"></div>
            </div>
          </div>
        </div>
      </template>
    </GlSwiper>
  </div>
</template>

<style lang="scss">
.dv-scroll-ranking-board {
  width: 100%;
  height: 100%;
  color: #fff;
}

.row-item {
  display: flex;
  user-select: none;
  align-items: center;
  flex-direction: column;
}

.ranking-info {
  display: flex;
  width: 100%;
  font-size: 13px;
  align-items: center;
  flex: 1;
}

.ranking-info .rank {
  color: #1370fb;
}

.ranking-info .info-name {
  flex: 1;
}

.ranking-column {
  width: 100%;
  margin-top: 5px;
  flex: 1;
}

.ranking-column .inside-column {
  position: relative;
  border-radius: 1px;
  overflow: hidden;
}

.ranking-column .shine {
  position: absolute;
  left: 0%;
  top: 0;
  height: calc(100% - 2px);
  width: 100px;
  transform: translateX(-100%);
  animation: shine 3s ease-in-out infinite;
}

@keyframes shine {
  80% {
    left: 0%;
    transform: translateX(-100%);
  }

  100% {
    left: 100%;
    transform: translateX(0%);
  }
}
</style>
